// 网格组件
import React, { useState, useEffect, useCallback } from 'react'
import CustomComponents from '@components/custom-components';
import { mod360 } from '@utils/translate';
import calculateComponentPositonAndSize from '@utils/calculateComponentPositonAndSize';
import { setCurrComp, setComponent, setIsClickComponent } from '@/store/actions/visualdrag';

export default (props) => {
  let { data, curComponent, curComponentIndex, componentData, dispatch } = props;
  const pointList = ['lt', 't', 'rt', 'r', 'rb', 'b', 'lb', 'l']; // 八个方向
  const initialAngle = { // 每个点对应的初始角度
    lt: 0,
    t: 45,
    rt: 90,
    r: 135,
    rb: 180,
    b: 225,
    lb: 270,
    l: 315,
  };
  const angleToCursor = [ // 每个范围的角度对应的光标
    { start: 338, end: 23, cursor: 'nw' },
    { start: 23, end: 68, cursor: 'n' },
    { start: 68, end: 113, cursor: 'ne' },
    { start: 113, end: 158, cursor: 'e' },
    { start: 158, end: 203, cursor: 'se' },
    { start: 203, end: 248, cursor: 's' },
    { start: 248, end: 293, cursor: 'sw' },
    { start: 293, end: 338, cursor: 'w' },
  ];
  const [cursors, setcursors] = useState({});
  // 获取各点位光标名称
  const getCursor = () => {
    const rotate = mod360(curComponent.style.rotate) // 取余 360
    const result = {}
    let lastMatchIndex = -1 // 从上一个命中的角度的索引开始匹配下一个，降低时间复杂度

    pointList.forEach(point => {
      const angle = mod360(initialAngle[point] + rotate)
      const len = angleToCursor.length
      while (true) {
        lastMatchIndex = (lastMatchIndex + 1) % len
        const angleLimit = angleToCursor[lastMatchIndex]
        if (angle < 23 || angle >= 338) {
          result[point] = 'nw-resize'

          return
        }

        if (angleLimit.start <= angle && angle < angleLimit.end) {
          result[point] = angleLimit.cursor + '-resize'

          return
        }
      }
    })

    return result
  }
  useEffect(() => {
    if (curComponent) {
      let data = getCursor();
      setcursors(data);
    }
  }, [curComponent])

  // 选中组件高亮
  const isActive = () => {
    let res = false;
    if (data.id == curComponentIndex) {
      res = true;
    }
    return res;
  }

  // 点击小圆点时，可以进行放大缩小操作
  const handleMouseDownOnPoint = (point, e) => {
    dispatch(setIsClickComponent(true))
    e.stopPropagation()
    e.preventDefault()

    const { style } = props.data

    // 组件宽高比
    const proportion = style.width / style.height

    // 组件中心点
    const center = {
      x: style.left + style.width / 2,
      y: style.top + style.height / 2,
    }

    // 获取画布位移信息
    const editorRectInfo = document.getElementById('editor').getBoundingClientRect()

    // 当前点击坐标
    const curPoint = {
      x: e.clientX - editorRectInfo.left,
      y: e.clientY - editorRectInfo.top,
    }

    // 获取对称点的坐标
    const symmetricPoint = {
      x: center.x - (curPoint.x - center.x),
      y: center.y - (curPoint.y - center.y),
    }

    let isFirst = true

    const move = (moveEvent) => {
      // 第一次点击时也会触发 move，所以会有“刚点击组件但未移动，组件的大小却改变了”的情况发生
      // 因此第一次点击时不触发 move 事件
      if (isFirst) {
        isFirst = false
        return
      }

      const curPositon = {
        x: moveEvent.clientX - editorRectInfo.left,
        y: moveEvent.clientY - editorRectInfo.top,
      }

      calculateComponentPositonAndSize(point, style, curPositon, proportion, false, {
        center,
        curPoint,
        symmetricPoint,
      })
      // 修改当前组件样式
      let res = {
        index: curComponentIndex,
        component: {
          ...curComponent,
          style
        }
      };
      dispatch(setCurrComp(res))
    }

    const up = () => {
      document.removeEventListener('mousemove', move)
      document.removeEventListener('mouseup', up)
    }

    document.addEventListener('mousemove', move)
    document.addEventListener('mouseup', up)
  }

  // 设置小圆点样式信息
  const getPointStyle = useCallback((point) => {
    if (curComponent) {
      const { width, height } = curComponent.style
      const hasT = /t/.test(point)
      const hasB = /b/.test(point)
      const hasL = /l/.test(point)
      const hasR = /r/.test(point)
      let newLeft = 0
      let newTop = 0

      // 四个角的点
      if (point.length === 2) {
        newLeft = hasL ? 0 : width
        newTop = hasT ? 0 : height
      } else {
        // 上下两点的点，宽度居中
        if (hasT || hasB) {
          newLeft = width / 2
          newTop = hasT ? 0 : height
        }

        // 左右两边的点，高度居中
        if (hasL || hasR) {
          newLeft = hasL ? 0 : width
          newTop = Math.floor(height / 2)
        }
      }

      const style = {
        marginLeft: hasR ? '-4px' : '-4px',
        marginTop: '-4px',
        left: `${newLeft}px`,
        top: `${newTop}px`,
        cursor: cursors[point],
      }
      return style
    }
  }, [cursors, curComponent])

  // 处理旋转
  const handleRotate = (e) => {
    dispatch(setIsClickComponent(true))
    e.preventDefault()
    e.stopPropagation()
    // 初始坐标和初始角度
    const pos = curComponent.style
    const startY = e.clientY
    const startX = e.clientX
    const startRotate = pos.rotate

    // 获取元素中心点位置
    const rect = document.getElementById(`shapeDiv${curComponentIndex}`).getBoundingClientRect()
    const centerX = rect.left + rect.width / 2
    const centerY = rect.top + rect.height / 2
    // 旋转前的角度
    const rotateDegreeBefore = Math.atan2(startY - centerY, startX - centerX) / (Math.PI / 180)

    const move = (moveEvent) => {
      const curX = moveEvent.clientX
      const curY = moveEvent.clientY
      // 旋转后的角度
      const rotateDegreeAfter = Math.atan2(curY - centerY, curX - centerX) / (Math.PI / 180)
      // 获取旋转的角度值
      pos.rotate = (startRotate + rotateDegreeAfter - rotateDegreeBefore).toFixed(2) * 1;
      // 修改当前组件样式
      let res = {
        index: curComponentIndex,
        component: {
          ...curComponent,
          style: pos
        }
      };
      dispatch(setCurrComp(res))
    }

    const up = () => {
      document.removeEventListener('mousemove', move);
      document.removeEventListener('mouseup', up);
    }

    document.addEventListener('mousemove', move)
    document.addEventListener('mouseup', up)
  }

  return (
    <div className={`shape ${isActive() && 'active'}`}
      id={`shapeDiv${data.id}`}>
      {isActive() &&
        <span className="iconfont iconjiazai icon-xiangyouxuanzhuan"
          onMouseDown={(e) => handleRotate(e)}></span>}
      {isActive() && pointList.map((item, index) => {
        return (
          <div
            className="shape-point"
            onMouseDown={(e) => handleMouseDownOnPoint(item, e)}
            key={index}
            style={{ ...getPointStyle(item) }}>
          </div>
        )
      })}
      <CustomComponents data={data} />
    </div>
  );
}

